
class Point(object):
    # Magic Method: 函数名前后有两个下划线
    # 在__init__之前调用,__new__必须要返回实例化出来的实例，否则导致__init__不会调用
    # __new__是创建一个对象，__init__是初始化一个对象
    # def __new__(cls, *args, **kwargs):
    #     pass

    # 构造函数
    def __init__(self, x, y):
        if isinstance(x, int):
            self.x = x
        else:
            raise Exception('y must be int')

        if isinstance(y, int):
            self.y = y
        else:
            raise Exception('y must be int')

    # 析构函数
    def __del__(self):
        pass

    # 比较运算符--------------------------------
    def __cmp__(self, other):
        if isinstance(other, Point):
            print('does not support compare')
            return True
        else:
            raise Exception('cannot cmp, the type must be Point')

    def __lt__(self, other):
        if isinstance(other, Point):
            print('does not support less than')
            return True
        else:
            raise Exception('cannot lt, the type must be Point')

    def __gt__(self, other):
        if isinstance(other, Point):
            print('does not support greater than')
            return True
        else:
            raise Exception('cannot gt, the type must be Point')

    def __eq__(self, other):
        if isinstance(other, Point):
            if self.x == other.x and self.y == other.y:
                return True
            else:
                return False
        else:
            raise Exception('cannot eq, the type must be Point')

    # 算数运算符--------------------------------
    def __add__(self, other):
        if isinstance(other, Point):
            # return self.x + other.x, self.y + other.y
            self.x += other.x
            self.y += other.y
            return self
        else:
            raise Exception('cannot add, the type must be Point')

    def __sub__(self, other):
        if isinstance(other, Point):
            # return self.x - other.x, self.y - other.y
            self.x -= other.x
            self.y -= other.y
            return self
        else:
            raise Exception('cannot sub, the type must be Point')

    def __mul__(self, other):
        if isinstance(other, Point):
            # return self.x * other.x, self.y * other.y
            self.x *= other.x
            self.y *= other.y
            return self
        else:
            raise Exception('cannot mul, the type must be Point')

    def __truediv__(self, other):
        if isinstance(other, Point):
            # return self.x / other.x, self.y / other.y
            self.x /= other.x
            self.y /= other.y
            return self
        else:
            raise Exception('cannot div, the type must be Point')

    def __mod__(self, other):
        if isinstance(other, Point):
            # return self.x % other.x, self.y % other.y
            self.x %= other.x
            self.y %= other.y
            return self
        else:
            raise Exception('cannot mod, the type must be Point')

    # 逻辑运算符--------------------------------
    def __and__(self, other):
        if isinstance(other, Point):
            print('does not support and')
            return True   # self.x and other.x, self.y and other.y
        else:
            raise Exception('cannot and, the type must be Point')

    def __or__(self, other):
        if isinstance(other, Point):
            print('does not support or')
            return True   # self.x * other.x, self.y * other.y
        else:
            raise Exception('cannot or, the type must be Point')

    # 对象转为字符串显示
    def __str__(self):
        # return '(x = ' + str(self.x) + ', y = ' + str(self.y) + ')'
        return '(x = %d, y = %d)' % (self.x, self.y)

    # 调用dir返回的信息
    def __dir__(self):
        return self.__dict__.keys()

    #
    def __unicode__(self):
        pass

    # # 获取属性失败时的返回
    # def __getattr__(self, item):
    #     print("get %s failed" % item)
    #     return 0
    #
    # # 获取属性
    # def __getattribute__(self, item):
        # 不能使用self，会造成递归调用
        # return getattr(self, item)      #  maximum recursion depth exceeded while calling a Python object
        # return self.__dict__[item]      # maximum recursion depth exceeded while calling a Python object
        # return super(Point, self).__getattribute__(item)
        # if item == 'x' or item == 'y':
        #     return '%s is get' % item
        # else:
        #     return object.__getattribute__(self, item)


p1 = Point(1, 5)
p2 = Point(2, 4)
print('p1: %s' % p1)                        # p1: (x = 1, y = 5)
print('p2: %s' % str(p2))                   # p2: (x = 2, y = 4)
print('dir(p1): %s' % dir(p1))              # dir(p1): ['x', 'y']
print('dir(p2): %s' % dir(p2))              # dir(p2): ['x', 'y']
print('p1 == p1: %s' % (p1 == p1))          # 等同于p1.__eq__(p1)
print('p1 == p2: %s' % (p1 == p2))          # 等同于p1.__eq__(p2).__str__()
print('p1 + p2 = %s' % (p1 + p2))           # p1 + p2 = (x = 3, y = 9)
print('p1 - p2 = %s' % (p1 - p2))           # p1 - p2 = (x = 1, y = 5)
print('p1 * p2 = %s' % (p1 * p2))           # p1 * p2 = (x = 2, y = 20)
print('p1 / p2 = %s' % (p1 / p2))           # p1 / p2 = (x = 1, y = 5)
# print('p1 % p2 = %s' % (p1 % p2))
print('p1 and p2 = %s' % (p1 and p2).__str__())     # p1 and p2 = (x = 2, y = 4)
print('p1 or p2 = %s' % (p1 or p2).__str__())       # p1 or p2 = (x = 1, y = 5)

# print('p.x = %s' % p1.__getattribute__('x'))
# print('p.y = %s' % p1.__getattribute__('y'))

